package ltd.smallwang.infrastructure.util;

import cn.hutool.core.codec.Base64;
import com.alibaba.cola.exception.SysException;
import com.google.crypto.tink.Aead;
import com.google.crypto.tink.CleartextKeysetHandle;
import com.google.crypto.tink.JsonKeysetReader;
import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.config.TinkConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;

@Slf4j
public class CryptoUtil {

  private static Aead aead;

  static {
    try {
      TinkConfig.register();
      try (InputStream secretFileInputStream = getSecretFile()) {
        KeysetHandle keysetHandle = CleartextKeysetHandle.read(
            JsonKeysetReader.withInputStream(secretFileInputStream));
        aead = keysetHandle.getPrimitive(Aead.class);
      }
    } catch (GeneralSecurityException | IOException e) {
      log.error("tink init error", e);
    }
  }

  private CryptoUtil() {
  }

  public static String encrypt(String plaintext) {
    byte[] encrypt;
    try {
      encrypt = aead.encrypt(plaintext.getBytes(StandardCharsets.UTF_8), null);
    } catch (GeneralSecurityException e) {
      log.error("encrypt error", e);
      throw new SysException("encrypt error");
    }
    return Base64.encode(encrypt);
  }

  public static String decrypt(String encryptStr) {
    try {
      byte[] decrypt = aead.decrypt(Base64.decode(encryptStr), null);
      return new String(decrypt, StandardCharsets.UTF_8);
    } catch (GeneralSecurityException e) {
      log.error("decrypt error", e);
      throw new SysException("decrypt error");
    }
  }

  private static InputStream getSecretFile() throws IOException {
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources("classpath*:tink_credentials.json");
    if (resources.length == 0) {
      throw new SysException("tink credential file is not found, pls check");
    }
    return resources[0].getInputStream();
  }
}
